/**
 * @class   wosh::Object
 * @brief   Base class of most WOSH classes
 *
 *









Common Compiler warnings/errors:

 warning C4250: 'wosh::YourObjectImplementation' : inherits 'Object::toString' via dominance
	class inherits Object and ISerializable. it's fine but to be explicit define method of use:
	using Object::toString;

 error C2248: 'wosh::XX::XX' : cannot access private member declared in class 'wosh::XX'
	you must explicitly define a (public/private) copy contructor or declare class 
	WOSH_COPY_FORBIDDEN(wosh::YourClass)












 ****************************************************************************
 * @version 0.8.499 $Id: Object.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_Object_H__
 #define __WOSH_Core_Object_H__

 #include <woshDefs.h>
 #include <core/Permission.h>
 #include <core/URI.h>
 #include <core/Serialization.h>


namespace wosh {

 #define _KEY_id				"ObjectId"
 #define _KEY_entity			"ObjectEntity"
 #define _KEY_name				"ObjectName"
 #define _KEY_type				"ObjectType"
 #define _KEY_owner				"ObjectOwner"
 #define _KEY_group				"ObjectGroup"
 #define _KEY_rights			"ObjectRights"
 #define _KEY_parent			"ObjectParent"

 #define _KEY_interfaces		"Interfaces"
 #define _KEY_Version			"Version"
 #define _KEY_DebugLevel		"DebugLevel"

class Object;
void object_assign( Object* object, const std::string& entity_id );

class Object : public virtual ISerializable
 {
	WOSH_CLASSNAME(wosh::Object)
	WOSH_CLASS_ABSTRACT(false)
	WOSH_CLONE_CONSTRUCTOR(wosh::Object)
	WOSH_COMPARE_RTTI(wosh::Object)

	public:
		/**
		 * @brief  Empty constructor with optional initializer.
		 * @param parent [in] pointer to object's parent
		 * @see    setParentObject()
		 */
		Object( const Object* parent = NULL );
		/**
		 * @brief  Constructor with parent/name initializer.
		 * @param parent [in] pointer to object's parent
		 * @param name [in] name of the object
		 * @see    setParentObject()
		 * @see    setName()
		 */
		Object( const Object* parent, const std::string& name );
		/**
		 * @brief  Constructor with many initializer.
		 * @param parent [in] pointer to object's parent
		 * @param name [in] name of the object
		 * @param uri [in] URI of the object
		 * @param permission [in] permission of the object
		 * @see    setParentObject()
		 * @see    setName()
		 * @see    setURI()
		 * @see    setPermission()
		 */
		Object( const Object* parent, const std::string& name, const URI& uri, const Permission& permission );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		Object( const Object& m );
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Object() { }


/** @name Getters
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief  Get the name (string) associated with the object
		 * @return returns (constant) STL string reference (to internal field)
		 */
		virtual const std::string& getName() const				{ return this->objName; }

		/**
		 * @brief  Get the name entity ID of the object.
		 *         Object identity, a unique identifier generated with the object creation
		 *         (or deserialization) and follows it throughout its life cycle
		 * @return returns (constant) STL string reference (to internal field)
		 */
		const std::string& getEntityID() const					{ return this->objEntityID; }

		/**
		 * @brief  Get the Permission object associated with the object
		 * @return returns (constant) Permission reference
		 */
		virtual const Permission& getPermission() const			{ return this->objPermission; }

		/**
		 * @brief  Get the URI object associated with the object
		 * @return returns (constant) URI reference
		 */
		virtual const URI& getURI() const						{ return this->objURI; }
		virtual URI& getURI()									{ return this->objURI; }

		/**
		 * @brief  Get the pointer to parent object
		 * @return returns (constant) pointer to parent object. May be NULL.
		 */
		virtual const Object* getParentObject()	const 			{ return this->objParent; }

//@}
/** @name Setters
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief  Set the name (string) associated with the object, it will also update URI's name.
		 * @param value [in] the name of the object as STL string
		 */
		virtual void setName( const std::string& value );
		/**
		 * @brief  Set the name of the object joining basename and id parameters. Provided for convenience.
		 * @param basename [in] the name of the object as STL string
		 * @param id [in] the id to be set
		 * @see   Utilities::format("%s#%ld", id)
		 */
		virtual void setName( const std::string& basename, long id );

		/**
		 * @brief  Set the Permission object associated with the object
		 * @param [in] value the Permission object to be set (copied)
		 */
		virtual void setPermission( const Permission& value )	{ this->objPermission = value; }

		virtual void setPermission( const Permission& value, short overwrite_mode, bool when_empty = false ) {
			this->objPermission.inherit(value, overwrite_mode, when_empty );
		 }

		/**
		 * @brief  Set the URI object associated with the object
		 * @param [in] value the URI object to be set (copied)
		 */
		virtual void setURI( const URI& value )					{ this->objURI = value; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:
		virtual Object& operator=( const Object& m );
		virtual bool operator==( const Object &other ) const;
		virtual bool operator!=(const Object &other) const		{ return !(*this == other);  }
//@}
/** @name Serialization Interface
 * @{
 ******************************************************************************/
	public:
		virtual inline std::string toString() const				{ return getName(); }
		virtual bool updateHash( DataHashContext* hash_context ) const;
//@}
	protected:
		virtual void setParentObject( const Object* parent );

	protected:
		std::string objEntityID;	///< entity ID of the object [unique worldwide]
		std::string objName;		///< name of the object
		Permission objPermission;	///< permissions of the object
		URI objURI;					///< URI of the object
		const Object* objParent;	///< parent reference of the object

		friend void object_assign( Object* object, const std::string& entity_id );

}; // class def



template <class T> class DataFieldCollector;


class ObjectTypeInfo : public ISerializable
 {
	WOSH_SERIALIZABLE(wosh::ObjectTypeInfo)
	WOSH_COMPARE_RTTI(wosh::ObjectTypeInfo)

	public:
		ObjectTypeInfo()
			: version(0.0), allocable(false) { }

		ObjectTypeInfo( const char* className, const char* parent_interface = "", double current_version = 0.0, bool abstract_class = false )
			: name(className), version(current_version), parent(parent_interface), allocable(!abstract_class) {}

		ObjectTypeInfo( const ObjectTypeInfo& m )
			: name(m.name), version(m.version), parent(m.parent), allocable(m.allocable) { }

		~ObjectTypeInfo() { }


/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline const std::string& getName() const		{ return this->name; }
		inline std::string& getName()					{ return this->name; }

		inline double getVersion() const				{ return this->version; }

		inline const std::string& getParent() const		{ return this->parent; }
		inline std::string& getParent()					{ return this->parent; }

		inline bool isAllocable() const					{ return this->allocable; }

		static DataFieldCollector<ObjectTypeInfo>* getDataFields();

//@}
/** @name Setters
 * @{
 ******************************************************************************/
	public:
		inline void setName( const std::string& value ) { this->name = value; }
		inline void setVersion( double value )			{ this->version = value; }
		inline void setParent( const std::string& value ) { this->parent = value; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:
		ObjectTypeInfo& operator=(const ObjectTypeInfo& m);
		bool operator==(const ObjectTypeInfo &other) const;
		bool operator!=(const ObjectTypeInfo &other) const { return !(*this == other);  }
		bool operator>(const ObjectTypeInfo& other) const;
		bool operator<(const ObjectTypeInfo& other) const;
//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		std::string toString() const;
		bool updateHash( DataHashContext* hash_context ) const;
//@}
	public:
		std::string name;
		double version;
		std::string parent;
		bool allocable;

}; // class def


}; // namespace wosh

#endif //__WOSH_Core_Object_H__
